﻿using System;
using System.Collections.Generic;
using Liber;
using Liber.BizTools;
using Liber.SOA;
using Liber.ORM;

namespace SoBusiness.App
{
    public class SaleApp:SOAUnit
    {
        public SaleApp(SOAHost _host)
            : base(_host)
        {

        }

        [API("SummaryOrderWithProcess")]
        FnResult<DyObject> SummaryOrderWithProcess(SOARequestContext rq)
        {
            long uid = rq.RequestContext.GetOrDefault<long>("uid", -1);
            bool onlymine = rq.RequestContext.GetOrDefault<bool>("onlymine", true);

            if (onlymine == true)
            {
                var cnt = Host.ORM.DB.PG().Query(@"SELECT
                                                COUNT(po.ID) AS pending
                                                FROM vt_trade as vt
                                                LEFT JOIN at_order po ON po.ID = vt.ID
                                                AND po.status = 'Pending'  
                                                WHERE vt.saler_id =" + uid);
                var r = new DyObject();
                if (cnt.Count > 0)
                {
                    r.Set("pending", cnt[0]["pending"]);
                }
                return FnResult<DyObject>.Sucess(r);
            }
            else
            {
                var cnt = Host.ORM.DB.PG().Query(string.Format(@"SELECT
                                                COUNT(po.ID) AS pending
                                                FROM vt_trade as vt
                                                LEFT JOIN at_order po ON po.ID = vt.ID
                                                AND po.status = 'Pending'  
                                                Where EXISTS ({0})", Host.ORM.DB.PG().Select<Org>("a.id").As("a")
                                                                                           .Where("id").Eq("@[vt.supplier_deptid]")
                                                                                           .With<Org>().As("p")
                                                                                           .Join<OrgPosition>().As("r1")
                                                                                           .Where("orgid").Eq("@[p.id]")
                                                                                           .Join<BORelation>().As("r2")
                                                                                           .Where("objid").Eq("@[r1.id]")
                                                                                           .And("srcid").Eq(uid)
                                                                                           .And("rtype").Eq("Acnt-Mainposition")
                                                                                           .Or("rtype", true).Eq("Acnt-Partposition")
                                                                                        .RecursiveBy().As("b")
                                                                                           .Where("id").Eq("@[a.parentid]")
                                                                                           .Or("parentid", true).Eq("@[a.id]").ToString()));
                var r = new DyObject();
                if (cnt.Count > 0)
                {
                    r.Set("pending", cnt[0]["pending"]);
                }
                return FnResult<DyObject>.Sucess(r);
            }

        }

        [API("QueryOrder")]
        FnResult<DyObject> QueryOrder(SOARequestContext rq)
        {
            long uid = rq.RequestContext.GetOrDefault<long>("uid", -1);
            bool onlycount = rq.RequestContext.GetOrDefault<bool>("onlycount", false);
            bool onlyMine = rq.RequestContext.GetOrDefault<bool>("onlymine", true);
            string status = rq.RequestContext.GetOrDefault<string>("status", "pending");
            string flag = rq.RequestContext.GetOrDefault<string>("flag", ""); //toDelivery,toPay,toStockIn
            string ordDate = rq.RequestContext.GetOrDefault<string>("ordDate", "recent");  //recent,thisWeek,preWeek,thisMonth
            string dlvDate = rq.RequestContext.GetOrDefault<string>("dlvDate", "all");  //today,thisWeek,nextWeek
            string ordDateStart = rq.RequestContext.GetOrDefault<string>("ordDateStart", "");
            string ordDateEnd = rq.RequestContext.GetOrDefault<string>("ordDateEnd", "");
            string dlvDateStart = rq.RequestContext.GetOrDefault<string>("dlvDateStart", "");
            string dlvDateEnd = rq.RequestContext.GetOrDefault<string>("dlvDateEnd", "");
            string client = rq.RequestContext.GetOrDefault<string>("client", "");
            string buyer = rq.RequestContext.GetOrDefault<string>("buyer", "");
            string ordserial = rq.RequestContext.GetOrDefault<string>("ordserial", "");

            int page = rq.RequestContext.GetOrDefault<int>("page", -1);
            int num = rq.RequestContext.GetOrDefault<int>("num", 20);
            string desc = rq.RequestContext.GetOrDefault<string>("desc", "");
            string asc = rq.RequestContext.GetOrDefault<string>("asc", "");

            PGSQLHelper cmd = Host.ORM.DB.PG().Select<Trade>(onlycount?"count(1) as total":"").As("od")
                                     .Where("isdeleted").Eq(false) as PGSQLHelper;
            cmd.And("iscurrentver").Eq(true);

            //处理订单编号筛选
            if (!string.IsNullOrWhiteSpace(ordserial))
            {
                cmd.And("src_orderserial").Like("%" + ordserial + "%");
            }
            else
            {
                //处理发布时间范围筛选
                DateTime ods = DateTime.MinValue;
                DateTime ode = DateTime.MinValue;
                DateTime.TryParse(ordDateStart, out ods);
                DateTime.TryParse(ordDateEnd, out ode);
                if (ods != DateTime.MinValue && ode != DateTime.MinValue)
                {
                    cmd.And("src_orderdate").BiggerOrEq(ods)
                        .And("src_orderdate", true).Smaller(ode.AddDays(1));
                }
                else if (ordDate == "recent")
                {
                    DateTime dt = DateTime.Today.AddDays(1);
                    DateTime rt = dt.AddDays(-3);
                    cmd.And("src_orderdate").BiggerOrEq(rt)
                       .And("src_orderdate", true).Smaller(dt);
                }
                else if (ordDate == "thisWeek")
                {
                    DateTime dt = DateTime.Today;
                    DateTime startWeek = dt.AddDays(0 - Convert.ToInt32(dt.DayOfWeek.ToString("d")));  //本周周一  
                    DateTime endWeek = startWeek.AddDays(7);  //下周一 

                    cmd.And("src_orderdate").BiggerOrEq(startWeek)
                       .And("src_orderdate", true).Smaller(endWeek);
                }
                else if (ordDate == "preWeek")
                {
                    DateTime dt = DateTime.Today;
                    DateTime startWeek = dt.AddDays(-7 - Convert.ToInt32(dt.DayOfWeek.ToString("d")));  //上周周日 
                    DateTime endWeek = startWeek.AddDays(7);  //本周周日  

                    cmd.And("src_orderdate").BiggerOrEq(startWeek)
                        .And("src_orderdate", true).Smaller(endWeek);
                }
                else if (ordDate == "thisMonth")
                {
                    DateTime dt = DateTime.Today;
                    DateTime startMonth = dt.AddDays(1 - dt.Day);  //本月月初  
                    DateTime endMonth = startMonth.AddMonths(1);  //下月一号  
                    cmd.And("src_orderdate").BiggerOrEq(startMonth)
                       .And("src_orderdate", true).Smaller(endMonth);
                }
                else { }


                //处理发货日期筛选
                DateTime dlvs = DateTime.MinValue;
                DateTime dlve = DateTime.MinValue;
                DateTime.TryParse(dlvDateStart, out dlvs);
                DateTime.TryParse(dlvDateEnd, out dlve);
                if (dlvs != DateTime.MinValue && dlve != DateTime.MinValue)
                {
                    cmd.And("deliverydate").BiggerOrEq(dlvs)
                       .And("deliverydate", true).Smaller(dlve.AddDays(1));
                }
                else if (dlvDate == "today")
                {
                    DateTime dt = DateTime.Today;
                    cmd.And("deliverydate").BiggerOrEq(dt)
                       .And("deliverydate", true).Smaller(dt.AddDays(1));
                }
                else if (dlvDate == "thisWeek")
                {
                    DateTime dt = DateTime.Today;
                    DateTime startWeek = dt.AddDays(0 - Convert.ToInt32(dt.DayOfWeek.ToString("d")));  //本周周一  
                    DateTime endWeek = startWeek.AddDays(7);  //下周一 

                    cmd.And("deliverydate").BiggerOrEq(startWeek)
                       .And("deliverydate", true).Smaller(endWeek);
                }
                else if (dlvDate == "nextWeek")
                {
                    DateTime dt = DateTime.Today;
                    DateTime startWeek = dt.AddDays(7 - Convert.ToInt32(dt.DayOfWeek.ToString("d")));  //下周周一
                    DateTime endWeek = startWeek.AddDays(7);  //下下周周一  
                    cmd.And("deliverydate").BiggerOrEq(startWeek)
                       .And("deliverydate", true).Smaller(endWeek);
                }
                else { }

                //处理客户名称
                if (!string.IsNullOrEmpty(client))
                {
                    cmd.And("src_client").Like("%" + client + "%")
                        .Or("invoiceheading", true).Like("%" + client + "%");
                }

                //处理采购员
                if (!string.IsNullOrEmpty(buyer))
                {
                    cmd.And("src_buyer").Like("%" + buyer + "%");
                }
            }
            

            //处理数据权限
            if (!onlyMine)
            {
                //TODO:通过参数控制用哪种数据过滤模式

                //模式1：操作员所属公司与订单所属公司一致
                //LiberBizHelper.OrgSVC.InSameCompany(ref cmd, "supplier_id", uid);

                //模式2：操作员所属部门与订单所属部门一致或属于其上级部门
                LiberBizHelper.OrgSVC.InUpOrgTree(ref cmd,"@[od.supplier_deptid]",uid);
            }
            else
            {
                cmd.And("saler_id").Eq(uid);
            }

            //处理分页
            if (page > 0&&!onlycount)
            {
                cmd.Limit(num)
                    .Offset((page - 1) * num);
            }

            //处理排序
            if (!onlycount)
            {
                if (!string.IsNullOrEmpty(asc))
                {
                    cmd.AscBy(asc=="dlvdate"?"deliverydate":"od.updatetime");
                }
                if (!string.IsNullOrEmpty(desc))
                {
                    cmd.DescBy(desc == "orderdate" ? "src_orderdate" : "od.updatetime");
                }
            }

            //处理关联进度
            if (flag == "toDelivery")
            {
                cmd.And("status").Eq(BizObjLifeStatus.Active)
                   .And("[tp_dlv.amount]").IsNULL()
                   .Or("[tp_dlv.amount]", true).Smaller("@[od.amount]")
                   .And("[tp_stkn.amount]").Smaller("@[od.amount]")
                   .Or("[tp_stkn.amount]", true).IsNULL()
                   .LeftJoin<TradeProcess>(onlycount ? "" : "@.amount as totaldelivery").As("tp_dlv")
                   .Where("orderid").Eq("@[od.id]")
                   .And("processtype").Eq("Delivery")
                   .And("status").Eq(BizObjLifeStatus.Completed)
                   .LeftJoin<TradeProcess>(onlycount ? "" : "@.amount as totalstockin").As("tp_stkn")
                   .Where("orderid").Eq("@[od.id]")
                   .And("processtype").Eq("StockInSum")
                   .And("status").Eq(BizObjLifeStatus.Completed);
            }
            else if (flag == "toStockIn")
            {
                cmd.And("status").Eq(BizObjLifeStatus.Active)
                   .And("[tp_dlv.amount]").NotNull()
                   .And("[tp_stkn.amount]").Smaller("@[tp_dlv.amount]")
                   .Or("[tp_stkn.amount]", true).IsNULL()
                   .LeftJoin<TradeProcess>(onlycount ? "" : "@.amount as totaldelivery").As("tp_dlv")
                   .Where("orderid").Eq("@[od.id]")
                   .And("processtype").Eq("Delivery")
                   .And("status").Eq(BizObjLifeStatus.Completed)
                   .LeftJoin<TradeProcess>(onlycount ? "" : "@.amount as totalstockin").As("tp_stkn")
                   .Where("orderid").Eq("@[od.id]")
                   .And("processtype").Eq("StockInSum")
                   .And("status").Eq(BizObjLifeStatus.Completed);
            }
            else if (flag == "toPay")
            {
                //TODO:需要抓取付款进度
            }
            else
            {
                var st = status.ToBizObjLifeStatus();
                if (st != BizObjLifeStatus.Unknow)
                {
                    cmd.And("status").Eq(st);
                }

                cmd.LeftJoin<TradeProcess>(onlycount ? "" : "@.amount as totaldelivery").As("tp_dlv")
                   .Where("orderid").Eq("@[od.id]")
                   .And("processtype").Eq("Delivery")
                   .And("status").Eq(BizObjLifeStatus.Completed)
                   .LeftJoin<TradeProcess>(onlycount ? "" : "@.amount as totalstockin").As("tp_stkn")
                   .Where("orderid").Eq("@[od.id]")
                   .And("processtype").Eq("StockInSum")
                   .And("status").Eq(BizObjLifeStatus.Completed);
            }

            var data = cmd.Query();

            if (!onlycount)
            {
                return FnResult<DyObject>.Sucess(DyObject.FromObjList("Orders", data));
            }
            else
            {
                return FnResult<DyObject>.Sucess(new DyObject().Set("Total", data[0]["total"]));
            }
        }


        [API("QueryDeliveries")]
        FnResult<DyObject> QueryDeliveries(SOARequestContext rq)
        {
            long uid = rq.RequestContext.GetOrDefault<long>("uid", -1);
            bool onlycount = rq.RequestContext.GetOrDefault<bool>("onlycount", false);
            bool onlyMine = rq.RequestContext.GetOrDefault<bool>("onlymine", true);
            string status = rq.RequestContext.GetOrDefault<string>("status", "Active");
            string flag = rq.RequestContext.GetOrDefault<string>("flag", ""); //toDelivery,toPay,toStockIn
            string dlvDate = rq.RequestContext.GetOrDefault<string>("dlvDate", "all");  //today,thisWeek,nextWeek
            string dlvDateStart = rq.RequestContext.GetOrDefault<string>("dlvDateStart", "");
            string dlvDateEnd = rq.RequestContext.GetOrDefault<string>("dlvDateEnd", "");
            string client = rq.RequestContext.GetOrDefault<string>("client", "");
            string creater = rq.RequestContext.GetOrDefault<string>("creater", "");
            int page = rq.RequestContext.GetOrDefault<int>("page", -1);
            int num = rq.RequestContext.GetOrDefault<int>("num", 20);
            string desc = rq.RequestContext.GetOrDefault<string>("desc", "createtime");
            string asc = rq.RequestContext.GetOrDefault<string>("asc", "");

            PGSQLHelper cmd = Host.ORM.DB.PG().Select<DeliveryBill>(onlycount ? "count(1) as total" : "").As("dt")
                                     .Where("isdeleted").Eq(false) as PGSQLHelper;
            cmd.And("iscurrentver").Eq(true);

            //处理发货日期筛选
            DateTime dlvs = DateTime.MinValue;
            DateTime dlve = DateTime.MinValue;
            DateTime.TryParse(dlvDateStart, out dlvs);
            DateTime.TryParse(dlvDateEnd, out dlve);
            if (dlvs != DateTime.MinValue && dlve != DateTime.MinValue)
            {
                cmd.And("createtime").BiggerOrEq(dlvs)
                   .And("createtime", true).Smaller(dlve.AddDays(1));
            }
            else if (dlvDate == "today")
            {
                DateTime dt = DateTime.Today;
                cmd.And("createtime").BiggerOrEq(dt)
                   .And("createtime", true).Smaller(dt.AddDays(1));
            }
            else if (dlvDate == "thisWeek")
            {
                DateTime dt = DateTime.Today;
                DateTime startWeek = dt.AddDays(0 - Convert.ToInt32(dt.DayOfWeek.ToString("d")));  //本周周一  
                DateTime endWeek = startWeek.AddDays(7);  //下周一 

                cmd.And("createtime").BiggerOrEq(startWeek)
                   .And("createtime", true).Smaller(endWeek);
            }
            else { }

            //处理状态
            BizObjLifeStatus st = status.ToBizObjLifeStatus();
            if (st != BizObjLifeStatus.Unknow)
            {
                cmd.And("status").Eq(st);
            }

            //处理分页
            if (page > 0 && !onlycount)
            {
                cmd.Limit(num)
                    .Offset((page - 1) * num);
            }

            //处理排序
            if (!onlycount)
            {
                if (!string.IsNullOrEmpty(asc))
                {
                    cmd.AscBy(asc == "createtime" ? "createtime" : "createtime");
                }
                if (!string.IsNullOrEmpty(desc))
                {
                    cmd.DescBy(desc == "createime" ? "createtime" : "createtime");
                }
            }

            //关联出必要的订单内容
            cmd.Join<BORelation>(!onlycount?"@.objid as orderid":"").As("od")
                .Where("srcid").Eq("@[dt.id]")
                .And("rtype").Eq("Order-Delivery")
                .Join<Trade>(!onlycount?"@.idstr as ordidstr,@.src_orderserial,@.src_consignee,@.consignee,@.consignee_phone,@.src_consigneephone,@.saler,@.saler_phone,@.buyer_phone,@.buyer,@.client_logo,@.client_realname,@.src_client,@.supplier_id":"").As("td")
                .Where("id").Eq("@[od.objid]");

            //处理客户名称
            if (!string.IsNullOrEmpty(client))
            {
                cmd.And("[td.src_client]").Like("%" + client + "%");
            }

            //处理发货员
            cmd.Join<Account>(!onlycount?"@.username as dlvcreater":"").As("at")
               .Where("id").Eq("@[dt.createrid]");

            if (!string.IsNullOrEmpty(creater))
            {
                cmd.And("[at.username]").Like("%" + creater + "%");
            }


            //处理数据权限
            LiberBizHelper.OrgSVC.InSameCompany(ref cmd, "@[td.supplier_id]", uid);  //仅限订单所属部门及其上级可见

            var data = cmd.Query();

            if (!onlycount)
            {
                return FnResult<DyObject>.Sucess(DyObject.FromObjList("Deliveries", data));
            }
            else
            {
                return FnResult<DyObject>.Sucess(new DyObject().Set("Total", data[0]["total"]));
            }
        }

        [API("ConfirmOrder")]
        FnResult<DyObject> ConfirmOrder(SOARequestContext cntx)
        {
            long uid = cntx.RequestContext.GetOrDefault<long>("uid", -1);
            long oid = cntx.RequestContext.GetOrDefault<long>("orderid", -1);

            //TODO:检查业务约束（例如：买方合作授权、采购廉政协议）

            PGSQLHelper cmd = LiberBizHelper.TradeSVC.UpdateOrder()
                                                     .Set("status", BizObjLifeStatus.Active)
                                                     .Where("id").Eq(oid)
                                                     as PGSQLHelper;

            LiberBizHelper.TODOSvc.CompleteTODO(ref cmd,"ConfirmOrder", oid);

            var rtn = cmd.GO();

            var buyer = LiberBizHelper.AcntSVC.GetUserByRelation(oid, "Order-Buyer");

            var order = LiberBizHelper.TradeSVC.GetOrder(-1, -1, -1, -1)
                                             .And("id").Eq(oid)
                                             .Query();
            if (buyer.Count>0&&order.Count>0)
            {
                if (buyer[0]["wxuser"].ToString()!="")
                {
                    string odserial = order[0]["idstr"].ToString();
                    if (order[0]["src_orderserial"] != null)
                    {
                        odserial = order[0]["src_orderserial"].ToString();
                        if (order[0]["src_orderversion"] != null)
                        {
                            odserial += '【' + order[0]["src_orderversion"].ToString() + '】';
                        }
                    }
                    DyObject wxmsg = new DyObject().Set("first", new DyObject().Set("value", "订单已确认")
                                                                               .Set("color", "#3987c5"))
                                                   .Set("OrderSn", new DyObject().Set("value", odserial)
                                                                                 .Set("color", "#666666"))
                                                   .Set("OrderStatus", new DyObject().Set("value", "执行中")
                                                                                     .Set("color", "#3987c5"))
                                                   .Set("remark", new DyObject().Set("value", order[0]["src_saler"]+"已确认您的订单，请关注微信消息或登录天联云协同平台跟进执行情况")
                                                                                .Set("color", "#666666"));

                    LiberBizHelper.UserMsgSVC.InformWechat(Name,"OrderConfirmed", buyer[0]["wxuser"].ToString(), oid,wxmsg);
                }
            }

            return rtn.IsPositive ? FnResult<DyObject>.Sucess(new DyObject().Set("idstr",oid.ToString())) : FnResult<DyObject>.Failure(rtn);

        }

        [API("NewDelivery")]
        FnResult<DyObject> NewDelivery(SOARequestContext cntx)
        {
            long uid = cntx.RequestContext.GetOrDefault<long>("uid", -1);
            var data = cntx.RequestContext.GetOrDefault<DyObject>("dlvdata", null);
            var mx = data["items"] as List<DyObject>;
            if (mx == null || mx.Count == 0)
            {
                return FnResult<DyObject>.Failure(Name, "RequiredArgs").SetError("items", "empty delivery mx");
            }
            try
            {
                if (data["arrivaltime"].ToString() == "")
                {
                    data["arrivaltime"] = DateTime.Today.AddDays(1);
                }
                if (data["dlvbillno"].ToString() == "")
                {
                    data["dlvbillno"] = IdFactory.NewID();
                }
                if (data["deliverier"].ToString() == "")
                {
                    data["deliverier"] = "未填写";
                }
                

                var rtn= LiberBizHelper.TradeSVC.NewDeliveryBill(uid, long.Parse(data["orderid"].ToString()), (DateTime)data["arrivaltime"], data["dlvbillno"].ToString(), data["deliverier"].ToString(),data["dlvmemo"].ToString(), mx);
                if (rtn.IsPositive)
                {
                    //TODO:通知收货人注意接收
                }
                return rtn;

            }
            catch (Exception ex)
            {
                return FnResult<DyObject>.Failure(Name, "NewDeliveryFailure").SetError("exception",ex.Message);
            }
        }


        [API("AbortDelivery")]
        FnResult<DyObject> AbortDelivery(SOARequestContext cntx)
        {
            long uid = cntx.RequestContext.GetOrDefault<long>("uid", -1);
            long dlvid = cntx.RequestContext.GetOrDefault<long>("dlvid", -1);

            var rtn = LiberBizHelper.TradeSVC.AbortDeliveryBill(uid, dlvid);
            return rtn;
        }
    }

}
